const queryString = require('query-string');

const parseJSON = (response) => {
  let contentType = response.headers.get('content-type'),
    isOk = response.ok,
    output = '';

  if (contentType && contentType.indexOf('application/json') !== -1) {
    output = response.json();
  } else {
    output = response.text();
  }

  if (isOk) {
    return output;
  }
  return output.then((res) => {
    if (typeof res === 'string') {
      throw new Error(res);
    } else {
      throw res.errorCode;
    }
  });
};

function handleErrors(response) {
  if (!response.ok) {
    throw Error(response.statusText);
  }
  return response;
}

const Hfetch = {
  defaultHeader: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  get(url, payload, options) {
    return fetch(`${url}?${queryString.stringify(payload)}`, Object.assign({}, {
      method: 'GET',
      headers: this.defaultHeader,
    }, options))
      .then(parseJSON, parseJSON);
  },
  post(url, payload, options) {
    return fetch(url, Object.assign({}, {
      method: 'POST',
      headers: this.defaultHeader,
      body: JSON.stringify(payload),
    }, options))
      .then(parseJSON, parseJSON);
  },
  put(url, payload, options) {
    return fetch(url, Object.assign({}, {
      method: 'PUT',
      headers: this.defaultHeader,
      body: JSON.stringify(payload),
    }, options)).then(handleErrors);
  },
  del(url, options) {
    return fetch(url, Object.assign({}, {
      method: 'DELETE',
      headers: this.defaultHeader,
    }, options)).then(handleErrors);
  },
  patch(url, payload, options) {
    return fetch(url, Object.assign({}, {
      method: 'PATCH',
      headers: this.defaultHeader,
      body: JSON.stringify(payload),
    }, options)).then(handleErrors);
  },
};

module.exports = Hfetch;
